#pragma once
#include "Epoller.hpp"
#include "Connection.hpp"
#include <memory>
#include <unordered_map>
class Reactor
{
    static const int defaultsize = 128;
private:
    int LoopOnce()
    {
        int timeout = -1;
        std::cout<<"进入LoopOnce"<<std::endl;
        int n = _epoller_ptr->WaitEvent(_revs, defaultsize, timeout);
        return n;
    }
    void Loop(int n)
    {
        for (int i = 0; i < n; i++)
        {
            int fd = _revs[i].data.fd;
            uint32_t event = _revs[i].events;

            // 1,所有异常处理,转换为IO错误
            // 2,所有的IO错误,转换为一个异常处理函数
            if (event & EPOLLHUP)
            {
                event |= (EPOLLIN | EPOLLOUT);
            }
            if (event & EPOLLERR)
            {
                event |= (EPOLLIN | EPOLLOUT);
            }
            if (event & EPOLLIN) // 关心读事件
            {
                // 先判断该链接是否存在
                if (IsConnectionExist(fd))
                {
                    _connections[fd]->Recver();
                }
            }
            if (event & EPOLLOUT) // 关心写事件
            {
                // 先判断该链接是否存在
                if (IsConnectionExist(fd))
                {
                    _connections[fd]->Sender();
                }
            }
        }
    }
public:
    Reactor()
        : _isrunning(false), _epoller_ptr(std::make_unique<Epoller>())
    {
    }
       void EnableWriteRead(int fd,bool read,bool write)
    {
        //首先我们需要判断该fd是否存在
        if(IsConnectionExist(fd))
        {
            //先改变_connection中的事件关心内容
            uint32_t events=(EPOLLET|(read?EPOLLIN:0)|(write?EPOLLOUT:0));
            _connections[fd]->SetEvents(events);
            //写透到内核当中
            _epoller_ptr->ModEvent(fd,events);
        }
        else
        {
            LOG(LogLevel::WARNING)<<"fd:"<<fd<<"不存在,无法设置读写事件关心...";
            return;
        }
    }
    bool IsConnectionExist(struct epoll_event revs)
    {
        int fd = revs.data.fd;
        auto it = _connections.find(fd);
        if (it == _connections.end())
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    bool IsConnectionExist(int fd)
    {
        auto it = _connections.find(fd);
        if (it == _connections.end())
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    void Start()
    {
        _isrunning = true;
        // 先判断Connection是否为空,若为空就直接返回
        if (_connections.empty())
        {
            return;
        }
        while (true)
        {
            PrintConnections();
            int n = LoopOnce();
            //std::cout << "在Start中n=" << n << std::endl;
            if (n > 0)
            {
                Loop(n);
            }
        }
        _isrunning = false;
    }
    // 向unordered_map中添加连接
    void AddConnection(std::shared_ptr<Connection> &conn)
    {
        int fd = conn->GetFd();
        uint32_t events = conn->GetEvents();
        _epoller_ptr->AddEvent(fd, events);
        conn->SetOwner(this);
        _connections[fd] = conn;
    }
    //删除链接_connections
    void DelConnection(int fd)
    {
        //首先我们需要判断该fd是否存在
        if(!IsConnectionExist(fd))
        {
            LOG(LogLevel::WARNING)<<"fd:"<<fd<<"不存在,无法设置读写事件关心...";
            return;
        }
        _epoller_ptr->DelEvent(fd);
        //从_connections当中删除
        _connections.erase(fd);
        //关闭该文件描述符
        close(fd);
        LOG(LogLevel::DEBUG)<<"用户fd:"<<fd<<"退出...";
    }
    //调试
    void PrintConnections()
    {
        std::cout<<"当前正在管理的fd与其关心事件:";
        for(auto it:_connections)
        {
            int fd=it.second->GetFd();
            uint32_t event=it.second->GetEvents();
            if(event&EPOLLOUT)
            {
                std::cout<<"fd:"<<fd<<"关心EPOLLOUT ";
            }
            else if(event&EPOLLIN)
            {
                std::cout<<"fd:"<<fd<<"关心EPOLLIN ";
            }
        }
        std::cout<<"\r\n";
    }
    ~Reactor()
    {
    }

private:
    // 需要一个Epoll模型
    std::unique_ptr<Epoller> _epoller_ptr;
    // 我们使用unordered_map管理Connection
    std::unordered_map<int, std::shared_ptr<Connection>> _connections;
    bool _isrunning;
    // 创建一个数组用于存放已经就绪的事件
    struct epoll_event _revs[defaultsize];
};